package com.example.frenchconjugationquiz;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.pm.ActivityInfo;
import android.content.res.AssetManager;
import android.graphics.Typeface;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.TextView;
import au.com.bytecode.opencsv.CSVReader;

import com.example.frenchconjugationquiz.data.CSVDataAdapter;
import com.example.frenchconjugationquiz.data.ConjugationDataSource;
import com.example.frenchconjugationquiz.data.ConjugationModel;
import com.example.frenchconjugationquiz.gui.CustomTextView;

import common.Utility;

public class SinglePlayerQuizActivity extends Activity
{	
	CustomTextView tvSubject,  tvVerb, tvTense, tvAnswer;
//	ImageButton btnAnswer;
	LinearLayout llAnswer;
	// btnPrev, btnNext, btnShuffle;
	FillDataTask task;
	ProgressDialog progressDialog;
	ConjugationDataSource dataSource;
	QuizManager quiz;

	private String CSV_PATH = "french-verb-conjugation-sample.csv";

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		Utility.Log("SinglePlayerQuizActivity created, opening DB");
		super.onCreate(savedInstanceState);

		initUI();

		dataSource = new ConjugationDataSource(this);
		dataSource.open();
		quiz = new QuizManager();
		// if (mDataSource.getCount() == 0)
		// {
		clearData();
		fillData();
		// }
	}

	private void initUI()
	{
		setContentView(R.layout.activity_single_player);

		tvSubject = (CustomTextView) findViewById(R.id.cctext_subject);
		tvVerb = (CustomTextView) findViewById(R.id.cctext_verb);
		tvTense = (CustomTextView) findViewById(R.id.cctext_tense);
		tvAnswer = (CustomTextView) findViewById(R.id.cctext_answer);
//		btnAnswer = (ImageButton) findViewById(R.id.btn_answer);
		llAnswer = (LinearLayout) findViewById(R.id.ll_answer);
		// btnPrev = (ImageButton) findViewById(R.id.btn_prev);
		// btnNext = (ImageButton) findViewById(R.id.btn_next);
		// btnShuffle = (ImageButton) findViewById(R.id.btn_shuffle);

		Typeface tf = Typeface.createFromAsset(getAssets(), "SFArchRival.ttf");
		tvSubject.setTypeface(tf);
		tvVerb.setTypeface(tf);
		tvTense.setTypeface(tf);
		tvAnswer.setTypeface(tf);
		
		this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

	}

	private void clearData()
	{
		Utility.Log("Clearing DB");
		dataSource.clearData();
	}

	private void fillData()
	{
		Utility.Log("fillData trying to parse csv");
		AssetManager assetManager = this.getAssets();
		try
		{
			InputStream csvStream = assetManager.open(CSV_PATH);
			task = new FillDataTask(this);
			task.execute(csvStream);
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	@Override
	protected void onPause()
	{
		if (progressDialog != null)
			progressDialog.dismiss();
		super.onPause();
	}

	@Override
	protected void onDestroy()
	{
		Utility.Log("SinglePlayerQuizActivity destroyed, closing DB");
		dataSource.close();
		super.onDestroy();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu)
	{
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_single_player_quiz, menu);
		return true;
	}

	public void goNext(View view)
	{
		quiz.getNext();
	}

	public void goPrev(View view)
	{
		quiz.getPrev();
	}

	public void shuffle(View view)
	{
		quiz.add(dataSource.getRandomModel());
	}

	public void showAnswer(View view)
	{
		quiz.showAnswer(true);
	}

	private class QuizQuestionNode
	{
		private QuizQuestionNode prev;
		private QuizQuestionNode next;
		private ConjugationModel data;
		private boolean isRevealed = false;

		public QuizQuestionNode(ConjugationModel data, QuizQuestionNode prev, QuizQuestionNode next)
		{
			this.prev = prev;
			this.next = next;
			this.data = data;
		}
	}

	private class QuizManager
	{
		QuizQuestionNode question;

		public void showAnswer(boolean b)
		{
			question.isRevealed = b;
			tvAnswer.setVisibility(b ? View.VISIBLE : View.GONE);
			llAnswer.setVisibility(b ? View.GONE : View.VISIBLE);
		}

		public boolean getPrev()
		{
			if (question != null && question.prev != null)
			{
				question = question.prev;
				questionChanged();
				return true;
			}
			else
			{
				Utility.Log("trying to reach a non existing prev question!");
				return false;
			}
		}

		private void questionChanged()
		{
			setQuiz(question.data);

			// first/last --> hide next prev
			// btnNext.setVisibility(question.next == null ? View.INVISIBLE :
			// View.VISIBLE);
			// btnPrev.setVisibility(question.prev == null ? View.INVISIBLE :
			// View.VISIBLE);
			showAnswer(question.isRevealed);
		}

		public boolean getNext()
		{
			if (question != null && question.next != null)
			{
				question = question.next;
				questionChanged();
				return true;
			}
			else
			{
				Utility.Log("trying to reach a non existing prev question!");
				return false;
			}
		}

		public void add(ConjugationModel data)
		{
			QuizQuestionNode newNode = new QuizQuestionNode(data, question, null);

			if (question != null)
			{
				question.next = newNode;
				newNode.prev = question;
			}
			question = newNode;
			questionChanged();
		}

		private void setQuiz(ConjugationModel conjugationModel)
		{
			Utility.Log(" Conjugation is set to : " + conjugationModel.getConjugation());
			tvSubject.setText(conjugationModel.getSubject());
			tvVerb.setText(conjugationModel.getVerb());
			tvTense.setText(conjugationModel.getTense());
			tvAnswer.setText(conjugationModel.getConjugation());
		}
	}

	private class FillDataTask extends AsyncTask<InputStream, Integer, Long>
	{
		private Context context;
		private String message = "Please wait while the conjugation table is downloaded ";

		public FillDataTask(Context context)
		{
			this.context = context;
		}

		@Override
		protected void onPreExecute()
		{
			super.onPreExecute();
			if (isCancelled())
				return;

			progressDialog = new ProgressDialog(context);
			progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener()
			{
				public void onCancel(DialogInterface dialog)
				{
					task.cancel(true);
					Utility.Log("Task cancelled.");
				}
			});
			progressDialog.setMessage(message);
			progressDialog.setCancelable(true);
			progressDialog.setIndeterminate(false);
			progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
			progressDialog.setMax(100);
			progressDialog.setProgress(0);
			progressDialog.show();
		}

		protected Long doInBackground(InputStream... csvStream)
		{
			Utility.Log("Task started.");
			progressDialog.setProgress(0);
			try
			{
				InputStreamReader csvStreamReader = new InputStreamReader(csvStream[0]);
				CSVReader csvReader = new CSVReader(csvStreamReader);
				String[] line;
				// throw away the header
				csvReader.readNext();
				while ((line = csvReader.readNext()) != null)
				{
					if (isCancelled())
						break;
					int total = CSVDataAdapter.addToDataSource(line, dataSource);
					Utility.Log(String.valueOf(total));
					publishProgress(total);
				}
				csvReader.close();
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}

			Utility.Log("Task finished.");
			return Long.MIN_VALUE;
		}

		protected void onProgressUpdate(Integer... progress)
		{
			int percentage = progress[0] * 100 / CSVDataAdapter.TOTAL_ENTRIES;
			Utility.Log("setting progress to " + progress[0]);
			progressDialog.setMessage(message + " : " + progress[0] + " of " + CSVDataAdapter.TOTAL_ENTRIES);
			progressDialog.setProgress(percentage);
		}

		protected void onPostExecute(Long result)
		{
			progressDialog.dismiss();
			// add first question
			shuffle(null);
		}
	}

}
